package cc.linker.steplink.crm.merchant.service;

import cc.linker.steplink.crm.commons.constant.OssConstant;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.service.CommonsService;
import cc.linker.steplink.crm.commons.utils.NumberUtils;
import cc.linker.steplink.crm.merchant.dao.EnrollDao;
import cc.linker.steplink.crm.merchant.dao.NewMallDao;
import cc.linker.steplink.crm.merchant.dao.ShopGoodsMapper;
import cc.linker.steplink.crm.merchant.dao.acs.PageDao;
import cc.linker.steplink.crm.merchanth5.dao.MallDao;
import cc.linker.steplink.crm.merchanth5.service.common.SmsService;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
public class EnrollService {

    @Autowired
    private EnrollDao enrollDao;
    @Autowired
    private PageDao pageDao;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private CommonsService commonsService;
    @Autowired
    private SmsService smsService;
    @Autowired
    private ShopGoodsMapper shopGoodsMapper;
    @Autowired
    private NewMallDao newMallDao;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private HttpService httpService;

    private static final String ENROLL_KEY = "enroll:enrollactive_limit_option_";

    public void addEnroll(Map<String, Object> param) {
        boolean ifAdd = StringUtils.isEmpty(param.get("enrollId"));
        String enrollId = ifAdd? UUID.randomUUID().toString():param.get("enrollId").toString();
        param.put("enrollId",enrollId);
        this.saveOption(param);
        this.saveAttribute(param);
        if (ifAdd) {
            enrollDao.addEnroll(param);
        } else {
            //编辑
            Integer recordCount = this.getRecordByEnrollId(param.get("enrollId").toString());
            if(recordCount>0){
                throw GlobalException.build("活动已开始，无法修改");
            }
            enrollDao.updateEnroll(param);
            enrollDao.delEnrollLabels(enrollId);
        }
        // 关联标签
        Object labels = param.get("labels");
        if (!StringUtils.isEmpty(labels)) {
            String[] split = labels.toString().split(",");
            if (split.length > 0) {
                enrollDao.updateEnrollLabels(enrollId, split);
            }
        }
    }

    public boolean updateEnroll(Map<String, Object> param) {
        this.saveOption(param);
        this.saveAttribute(param);
        return enrollDao.updateEnroll(param);
    }

    private void saveOption(Map<String, Object> param){
        enrollDao.delOption((String) param.get("enrollId"));
        List<Map<String, Object>> optionList = (List<Map<String, Object>>) param.get("optionJson");

        Date ttlTime = null;
        if (!StringUtils.isEmpty(param.get("endTime"))) {
            String endTime = (String) param.get("endTime");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                ttlTime = simpleDateFormat.parse(endTime);
            } catch (ParseException e) {
                ttlTime = null;
            }
        }

        if("0".equals(param.get("isEnroll").toString())){
            //若隐藏报名项，则生成一条虚拟报名项
            if (null == optionList || optionList.size() == 0) {
                Map<String, Object> vOptionParam = new HashMap<>();
                String optionId = UUID.randomUUID().toString();
                vOptionParam.put("enrollId", param.get("enrollId"));
                vOptionParam.put("optionId", optionId);
                vOptionParam.put("optionName", param.get("title"));
                vOptionParam.put("optionPrice", 0);
                vOptionParam.put("existNum", 0);
                vOptionParam.put("maxNum", 99999);
                vOptionParam.put("initNum", 0);
                String key = ENROLL_KEY + optionId;
                ArrayList<String> vOptionList = new ArrayList<>(Collections.nCopies(99999, "1"));
                stringRedisTemplate.opsForList().leftPushAll(key, vOptionList);
                if(null != ttlTime){
                    stringRedisTemplate.expireAt(key,ttlTime);
                }
                enrollDao.saveOption(vOptionParam);
            }
        }


        if (null != optionList && optionList.size() > 0) {
            List<Map<String, Object>> options = new ArrayList<>();
            int second = 1;
            for (Map<String, Object> da : optionList) {
                Integer initNum = 0;
                Integer maxNum = 0;
                if(!StringUtils.isEmpty(da.get("initNum"))){
                    initNum = Integer.valueOf(da.get("initNum").toString());
                }
                if(!StringUtils.isEmpty(da.get("maxNum"))){
                    maxNum = Integer.valueOf(da.get("maxNum").toString());
                }
                if(initNum>maxNum){
                    throw GlobalException.build(da.get("optionName")+"初始化报名人数不能大于最大报名数");
                }
                Integer existNum = initNum;
                if (StringUtils.isEmpty(da.get("optionId"))) {
                    da.put("optionId", UUID.randomUUID().toString());
                    if(StringUtils.isEmpty(da.get("optionName"))){
                        throw GlobalException.build("请填写报名项名称");
                    }
                }else{
                    Integer optionNum = enrollDao.getOptionNum((String) da.get("optionId"));
                    existNum = optionNum + initNum;
                }
                String key = ENROLL_KEY+da.get("optionId").toString();
                stringRedisTemplate.delete(key);

                da.put("existNum",existNum);

//                if(!StringUtils.isEmpty(da.get("optionPrice"))){
//                    Double optionPrice = Double.valueOf(da.get("optionPrice").toString()) * 100;
//                    da.put("optionPrice",optionPrice.intValue());
//                }
                da.put("enrollId", param.get("enrollId"));
                da.put("second", second);
                enrollDao.saveOption(da);
                second = second+1;
                options.add(da);
            }
            for( Map<String, Object> option:options){
                String key = ENROLL_KEY+option.get("optionId").toString();
                Integer initNum = 0;
                Integer maxNum = 0;
                if(!StringUtils.isEmpty(option.get("initNum"))){
                    initNum = Integer.valueOf(option.get("initNum").toString());
                }
                if(!StringUtils.isEmpty(option.get("maxNum"))){
                    maxNum = Integer.valueOf(option.get("maxNum").toString());
                }
                if((maxNum-initNum)>0){
                    int num = maxNum-initNum;
                    ArrayList<String> list = new ArrayList<>(Collections.nCopies(num,"1"));
                    stringRedisTemplate.opsForList().leftPushAll(key,list);

//                    ArrayList<String> list = new ArrayList<>();
//                    for (int i = 0; i < num; i++) {
//                        list.add("1");
//                    }
//                    stringRedisTemplate.opsForList().leftPushAll(key,list);
                    if(null != ttlTime){
                        stringRedisTemplate.expireAt(key,ttlTime);
                    }
                }
            }
        }
    }

    private void saveAttribute(Map<String, Object> param) {
        enrollDao.delAttribute((String) param.get("enrollId"));
        List<Map<String, Object>> attrList = (List<Map<String, Object>>) param.get("attrJson");
        if (null != attrList && attrList.size() > 0) {
            for (Map<String, Object> da : attrList) {
                if (StringUtils.isEmpty(da.get("attrId"))) {
                    da.put("attrId", UUID.randomUUID().toString());
                }
                da.put("enrollId", param.get("enrollId"));
                enrollDao.saveAttribute(da);
            }
        }
    }

    public Map<String, Object> getInfo(Map<String, String> param) {
        Map<String, Object> info = enrollDao.getInfo(param);
        List<Map<String, Object>> options = enrollDao.getOption(param.get("enrollId"));
        for(Map<String, Object> op:options){
            if(!StringUtils.isEmpty(op.get("optionPrice"))){
                op.put("optionPrice",NumberUtils.fenToYuan(Long.valueOf(op.get("optionPrice").toString())));
            }
        }
        info.put("options", options);
        info.put("attributes", enrollDao.getAttribute(param.get("enrollId")));
        //
        // 获取关联的标签
        List<Map<String, Object>> labels = enrollDao.getEnrollLabelsById(param.get("enrollId"));
        info.put("labels",labels);
        return info;
    }

    public List<Map<String, Object>> getList(Map<String, Object> map) {
        boolean ifSaler = (boolean)map.get("ifSaler");
        List<Map<String, Object>> res = enrollDao.getList(map);
        int finalStatus = map.get("status") == null ? 0 : Integer.parseInt(map.get("status").toString());
        res.forEach(x -> {
            String enrollId = x.get("enrollId").toString();
//            //TODO 获取第三方销量
//            x.put("otherSaleNum",0);
            //如果是小b查看活动列表，全部置为自由活动
            if(ifSaler){
                x.put("isShare","0");
            }
            Long price = enrollDao.getMinprice(enrollId);
            x.put("price", NumberUtils.fenToYuan(price));
            if (finalStatus > 0) {
                switch (finalStatus) {
                    case 1:
                        x.put("statusName", "待报名");
                        break;
                    case 2:
                        x.put("statusName", "报名中");
                        break;
                    case 3:
                        x.put("statusName", "报名结束");
                        break;
                    case 4:
                        x.put("statusName", "报名已满");
                        break;
                    default:
                        x.put("statusName", "报名关闭");
                        break;
                }
            } else {
                // 判断状态
                String startTime = x.get("startTime") == null ? "" : x.get("startTime").toString();
                String endTime = x.get("endTime") == null ? "" : x.get("endTime").toString();
                String status = x.get("status").toString();
                Date d = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String nowTime = sdf.format(d);
                // 获取已报名人数
                Integer realNum = enrollDao.getRealNum(enrollId);
                // 获取设置的报名总人数 减去 初始化的总人数
                Integer setNum = enrollDao.getSetNum(enrollId);
                // 获取是否存在不限人数的报名项
                Integer unlimited = enrollDao.unlimited(enrollId);
                if ("0".equals(status)) {
                    x.put("statusName", "报名关闭");
                } else if (!StringUtils.isEmpty(startTime) && nowTime.compareTo(startTime) < 0) {
                    // 待报名
                    x.put("statusName", "待报名");
                } else if (!StringUtils.isEmpty(endTime) && nowTime.compareTo(endTime) > 0) {
                    // 报名结束
                    x.put("statusName", "报名结束");
                } else if (unlimited < 1 && realNum >= setNum) {
                    // 报名已满
                    x.put("statusName", "报名已满");
                } else {
                    //报名中
                    x.put("statusName", "报名中");
                }
            }
        });
        return res;
    }

    public void changeEnrollStatus(String enrollId, String customerId){
        enrollDao.changeEnrollStatus(enrollId,customerId);
    }

    public void delEnroll(String enrollId, String customerId) {
        enrollDao.delEnroll(enrollId, customerId);
        // v1.11.15 删除活动时 删除报名组件中的活动
        pageDao.delModuleImageByEnrollId(enrollId);
    }

    public PageInfo myEnroll(Map<String, Object> param) {
        Integer pageIndex = (Integer) param.get("pageIndex");
        Integer pageSize = (Integer) param.get("pageSize");
        PageHelper.startPage(pageIndex, pageSize);
        List<Map<String, Object>> maps = enrollDao.listMyEnrollByCustomerId(param);
        return new PageInfo<>(maps);
    }

    public void setEnrollPromotion(Map<String, Object> param) {
        enrollDao.setEnrollPromotion(param);
    }

    public List<Map<String, Object>> recordList(Map<String, Object> map,List<String> attrIds) {
        List<Map<String, Object>> res = enrollDao.recordList(map);
        res.forEach(x->{
            x.put("payAmount",NumberUtils.fenToYuan(Long.parseLong(x.get("payAmount").toString())));
            List<Map<String,Object>> record = (List<Map<String,Object>>) JSONArray.parse(x.get("record").toString());
            x.put("record",record);
            if(attrIds!=null && attrIds.size()>0 && !StringUtils.isEmpty(x.get("record"))){
                List<Map> recordList = (List<Map>) x.get("record");
                recordList.forEach(y->{
                    if(!StringUtils.isEmpty(y.get("attrId"))){
                        String attrId = y.get("attrId").toString();
                        if(attrIds.contains(attrId)){
                            if(!StringUtils.isEmpty(y.get("attrValue"))){
                                List<Map> valueList =(List<Map>) y.get("attrValue");
                                List<String> valueNewList = new ArrayList<>();
                                valueList.forEach(z->{
                                    if(z.get("type").toString().equals("2")){
                                        String cover = "";
                                        String viodeurl = "";
                                        String sourceUrl = "";
                                        String transcodingState = "";
                                        //请求素材中心
                                        try {
                                            Map<String, Object> params = new HashMap<>();
                                            params.put("ResId",z.get("resId"));
                                            String url = systemProperties.getMaterialCenter() + OssConstant.OSS_INFO;
                                            String result = httpService.doPost(url, JSON.toJSONString(params), OssConstant.JSON);
                                            Map obj = JSONObject.parseObject(result);
                                            if(obj!=null && !StringUtils.isEmpty(obj.get("Code")) && "200".equals(obj.get("Code").toString())) {
                                                if (!StringUtils.isEmpty(obj.get("PreviewObj"))) {
                                                    Map previewObj = (Map) obj.get("PreviewObj");
                                                    if (previewObj != null && !StringUtils.isEmpty(previewObj.get("Url"))) {
                                                        viodeurl = previewObj.get("Url").toString();
                                                    }
                                                }
                                                if (!StringUtils.isEmpty(obj.get("SourceObj"))) {
                                                    Map sourceObj = (Map) obj.get("SourceObj");
                                                    if (sourceObj != null && !StringUtils.isEmpty(sourceObj.get("Url"))) {
                                                        sourceUrl = sourceObj.get("Url").toString();
                                                    }
                                                }
                                                if (!StringUtils.isEmpty(obj.get("TranscodingState"))) {
                                                    transcodingState = obj.get("TranscodingState").toString();
                                                }
                                                if (!StringUtils.isEmpty(obj.get("Thumbnail"))) {
                                                    cover = obj.get("Thumbnail").toString();
                                                }
                                            }
                                            Map videoMap = new HashMap();
                                            videoMap.put("cover",cover);
                                            videoMap.put("url",viodeurl);
                                            videoMap.put("sourceUrl",sourceUrl);
                                            videoMap.put("transcodingState",transcodingState);
                                            String a = JSONObject.toJSONString(videoMap);
                                            valueNewList.add(a);
                                        }catch (Exception e){
                                            Map videoMap = new HashMap();
                                            videoMap.put("cover","");
                                            videoMap.put("url","");
                                            videoMap.put("transcodingState",2);
                                            String a = JSONObject.toJSONString(videoMap);
                                            valueNewList.add(a);
                                        }
                                    }else {
                                        String a = "";
                                        if(!StringUtils.isEmpty(z.get("sourceUrl"))){
                                            a = z.get("sourceUrl").toString();
                                        }
                                        valueNewList.add(a);
                                    }
                                    y.remove("attrValue");
                                    y.put("attrValue",valueNewList);
                                });

                            }
                        }
                    }
                }
                );
            }
        });
        return res;
    }

    public Integer getRecordByEnrollId(String enrollId) {
        return enrollDao.getRecordByEnrollId(enrollId);
    }

    public void exportRecordList(Map<String, Object> map, HttpServletResponse response,List<String> attrIdsList) throws Exception
    {
        List<Map<String, Object>> list = enrollDao.recordList(map);
        List<String> listTitles = new ArrayList<>();
        listTitles.add("用户编号");
        listTitles.add("微信昵称");
        listTitles.add("手机号");
        listTitles.add("报名名称");
        List<String> listString = new ArrayList<>();
        listString.add("customerId");
        listString.add("customerName");
        listString.add("bindPhone");
        listString.add("title");
        // 查询活动下的 attr
        List<Map<String,Object>> attrList = enrollDao.getAttrList(map);
        for (int i = 0; i < attrList.size(); i++) {
            listTitles.add(attrList.get(i).get("attrTitle").toString());
            listString.add(attrList.get(i).get("attrId").toString());
        }
        list.forEach(x->{
            x.put("payAmount",NumberUtils.fenToYuan(Long.parseLong(x.get("payAmount").toString())));
            List<Map<String,Object>> record = (List<Map<String,Object>>) JSONArray.parse(x.get("record").toString());
            x.put("record",record);
            for (int i = 0; i < record.size(); i++) {
                Map<String,Object> temp = record.get(i);
                if(attrIdsList!=null && attrIdsList.size()>0){
                    int count = 0;
                    for(String attrId : attrIdsList){
                        if(attrId.equals(temp.get("attrId"))){
                            List<Map> alist = (List<Map>)temp.get("attrValue");
                            String a = "";
                            if(alist!=null && alist.size()>0){
                                for(Map b : alist){
                                    if("1".equals(b.get("type").toString())){
                                        a = a + ",\""+b.get("sourceUrl")+"\"";
                                    }else {
                                        a = a + ",\""+b.get("previewUrl")+"\"";
                                    }
                                }
                            }
                            if(a.startsWith(",")){
                                a = a.substring(1);
                            }
                            x.put(temp.get("attrId").toString(),a);
                            count = count + 1;
                        }
                    }
                    if(count==0){
                        x.put(temp.get("attrId").toString(),temp.get("attrValue").toString());
                    }
                }else {
                    x.put(temp.get("attrId").toString(),temp.get("attrValue").toString());
                }
            }
        });


        listTitles.add("报名时间");
        listTitles.add("报名项");
        listTitles.add("付款金额");
        listString.add("createTime");
        listString.add("optionName");
        listString.add("payAmount");

        String[] title = listTitles.toArray(new String[listTitles.size()]);
        String fileName = "报名人员名单";
        String[] strings = listString.toArray(new String[listString.size()]);
        commonsService.excelDownload(list, strings, title, fileName, response);
    }

    public void changeToShare(Map<String, String> param) {
        Map<String,Object> enrollInfo = enrollDao.getInfo(param);
        Map<String,Object> merParam = new HashMap<>();
        merParam.put("orgId",param.get("orgId"));
        if(!enrollInfo.get("orgId").equals(enrollInfo.get("customerId"))){
            merParam.put("customerId",enrollInfo.get("customerId"));
        }
        //  商家认证
        Map<String, Object> merInfo = newMallDao.getMerInfo(merParam);
        if (merInfo == null || !"2".equals(merInfo.get("checkStatus").toString())) {
            throw GlobalException.build("暂时无法添加，商家未进行认证");
        }
        enrollDao.changeToShare(param);
    }

    public List<Map<String, Object>> getShareList(Map<String, String> param) {
        List<Map<String, Object>> shareList = enrollDao.getShareList(param);
        for(Map<String, Object> data:shareList){
            Long minPrice = enrollDao.getMinprice(data.get("enrollId").toString());
            data.put("price",NumberUtils.fenToYuan(minPrice));
        }
        return shareList;
    }
    public List<Map<String, Object>> allianceShareList(Map<String, Object> param) {
        List<Map<String, Object>> shareList = enrollDao.allianceShareList(param);
        for(Map<String, Object> data:shareList){
            Long minPrice = enrollDao.getMinprice(data.get("enrollId").toString());
            data.put("price",NumberUtils.fenToYuan(minPrice));
            // 判断状态
            String startTime = data.get("startTime") == null ? "" : data.get("startTime").toString();
            String endTime = data.get("endTime") == null ? "" : data.get("endTime").toString();
            String status = data.get("status").toString();
            Date d = new Date();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String nowTime = sdf.format(d);
            // 获取已报名人数
            Integer realNum = enrollDao.getRealNum(data.get("enrollId").toString());
            // 获取设置的报名总人数 减去 初始化的总人数
            Integer setNum = enrollDao.getSetNum(data.get("enrollId").toString());
            // 获取是否存在不限人数的报名项
            Integer unlimited = enrollDao.unlimited(data.get("enrollId").toString());
            if ("0".equals(status)) {
                data.put("statusName", "报名关闭");
            } else if (!StringUtils.isEmpty(startTime) && nowTime.compareTo(startTime) < 0) {
                // 待报名
                data.put("statusName", "待报名");
            } else if (!StringUtils.isEmpty(endTime) && nowTime.compareTo(endTime) > 0) {
                // 报名结束
                data.put("statusName", "报名结束");
            } else if (unlimited < 1 && realNum >= setNum) {
                // 报名已满
                data.put("statusName", "报名已满");
            } else {
                //报名中
                data.put("statusName", "报名中");
            }
        }
        return shareList;
    }

    public void banned(Map<String, String> param) {
        enrollDao.banned(param);
        Map<String, Object> info = enrollDao.getInfo(param);
        String phone = shopGoodsMapper.getPhoneFromSalerByCustomerId(info.get("customerId").toString());
        if(StringUtils.isEmpty(phone)){
            LOGGER.warn("用户手机号不存在");
        }else{
            boolean flag = "0".equals(param.get("isSeal"));
            Map<String, Object> reqMap = new HashMap<>();
            // 9004 封禁 9005 解除封禁 product 商品 name 理由
            reqMap.put("businessType", flag ? "9005" : "9004");
            reqMap.put("mobilNumber", phone);
            Map<String, Object> paramMap = new HashMap<>();
            paramMap.put("product", info.get("title"));
            if (!flag) {
                paramMap.put("name", param.get("reason"));
            }
            reqMap.put("params", JSON.toJSONString(paramMap));
            String s = smsService.sendMsg(param.get("orgId"), reqMap);
            LOGGER.info("enrollbanned===" + s);
        }
    }

    public List<Map<String, Object>> getEnrollList(Map<String, Object> map) {
        boolean ifSaler = (boolean)map.get("ifSaler");
        List<Map<String, Object>> res = enrollDao.getEnrollList(map);
        int finalStatus = map.get("status") == null ? 0 : Integer.parseInt(map.get("status").toString());
        res.forEach(x -> {
            if (ifSaler) {
                x.put("isShare", "0");
            }
            String enrollId = x.get("enrollId").toString();
            Long price = enrollDao.getMinprice(enrollId);
            x.put("price", NumberUtils.fenToYuan(price));
            if (finalStatus > 0) {
                switch (finalStatus) {
                    case 1:
                        x.put("statusName", "待报名");
                        break;
                    case 2:
                        x.put("statusName", "报名中");
                        break;
                    case 3:
                        x.put("statusName", "报名结束");
                        break;
                    case 4:
                        x.put("statusName", "报名已满");
                        break;
                    default:
                        x.put("statusName", "报名关闭");
                        break;
                }
            } else {
                // 判断状态
                String startTime = x.get("startTime") == null ? "" : x.get("startTime").toString();
                String endTime = x.get("endTime") == null ? "" : x.get("endTime").toString();
                String status = x.get("status").toString();
                Date d = new Date();
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String nowTime = sdf.format(d);
                // 获取已报名人数
                Integer realNum = enrollDao.getRealNum(enrollId);
                // 获取设置的报名总人数 减去 初始化的总人数
                Integer setNum = enrollDao.getSetNum(enrollId);
                // 获取是否存在不限人数的报名项
                Integer unlimited = enrollDao.unlimited(enrollId);
                if ("0".equals(status)) {
                    x.put("statusName", "报名关闭");
                } else if (!StringUtils.isEmpty(startTime) && nowTime.compareTo(startTime) < 0) {
                    // 待报名
                    x.put("statusName", "待报名");
                } else if (!StringUtils.isEmpty(endTime) && nowTime.compareTo(endTime) > 0) {
                    // 报名结束
                    x.put("statusName", "报名结束");
                } else if (unlimited < 1 && realNum >= setNum) {
                    // 报名已满
                    x.put("statusName", "报名已满");
                } else {
                    //报名中
                    x.put("statusName", "报名中");
                }
            }
            // 查询关联的标签和名称
            List<Map<String,Object>> labels = enrollDao.getEnrollLabelsById(x.get("enrollId").toString());
            x.put("labels",labels);
        });
        return res;
    }
}
